#include "mytcpsocket.h"
#include <QDebug>
#include "mytcpserver.h"

MyTcpSocket::MyTcpSocket(QObject *parent)
    : QTcpSocket{parent}
{
    // 绑定接收信息的信号槽
    connect(this,SIGNAL(readyRead()),this,SLOT(recvMsg()));

    // 绑定断开连接的信号槽
    connect(this,SIGNAL(disconnected()),this,SLOT(clientOffline()));
}

QString MyTcpSocket::getName()
{
    return m_strName;
}

// 接收到请求，处理数据
void MyTcpSocket::recvMsg()
{
    qDebug() << this->bytesAvailable();
    uint uiPDULen = 0;
    this->read((char*)&uiPDULen,sizeof(uint));
    uint uiMsgLen = uiPDULen - sizeof(PDU); // 实际消息长度
    PDU *pdu = mkPDU(uiMsgLen);
    this->read((char*)pdu + sizeof(uint),uiPDULen - sizeof(uint)); // 读取，填充除了uiPDULen属性的其他部分.

    switch(pdu->uiMsgType) {
        // 注册
        case ENUM_MSG_TYPE_REGIST_REQUEST: {
            char caName[32] = {'\0'};
            char caPwd[32] = {'\0'};
            strncpy(caName, pdu->caData,32);
            strncpy(caPwd,pdu->caData+32,32);
            // 1.持久化数据
            bool ret = OpeDB::getInstance().handleRegist(caName,caPwd);
            // 2.组装返回响应信息
            PDU *respdu = mkPDU(0);
            respdu -> uiMsgType = ENUM_MSG_TYPE_REGIST_RESPOND;
            if(ret) {
                strcpy(respdu->caData,REGIST_OK);
            }else {
                strcpy(respdu->caData,REGIST_FAILED);
            }
            write((char*)respdu,respdu->uiPDULen);
            // 3.销毁报文空间
            free(respdu);
            respdu = NULL;
            break;
        }
        // 登录
        case ENUM_MSG_TYPE_LOGIN_REQUEST: {
            char caName[32] = {'\0'};
            char caPwd[32] = {'\0'};
            strncpy(caName, pdu->caData,32);
            strncpy(caPwd,pdu->caData+32,32);
            // 1.请求登录
            bool ret = OpeDB::getInstance().handleLogin(caName,caPwd);
            // 2.组装返回响应信息
            PDU *respdu = mkPDU(0);
            respdu -> uiMsgType = ENUM_MSG_TYPE_LOGIN_RESPOND;
            if(ret) {
                strcpy(respdu->caData,LOGIN_OK);
                m_strName = caName;
            }else {
                strcpy(respdu->caData,LOGIN_FAILED);
            }
            write((char*)respdu,respdu->uiPDULen);
            // 3.销毁报文空间
            free(respdu);
            respdu = NULL;
            break;
        }
        // 在线用户请求
        case ENUM_MSG_TYPE_ALL_ONLINE_REQUEST: {
            // 1.查找在线用户
            QStringList ret = OpeDB::getInstance().handleAllOnline();
            // 2.组装返回信息
            uint uiMsgLen = ret.size()*32;
            PDU *respdu = mkPDU(uiMsgLen);
            respdu->uiMsgType = ENUM_MSG_TYPE_ALL_ONLINE_RESPOND;
            for(int i = 0; i < ret.size(); i++) {
                memcpy((char*)(respdu->caMsg) + i*32, ret.at(i).toStdString().c_str(), ret.at(i).size());
            }
            // 3.返回响应
            write((char*)respdu,respdu->uiPDULen);
            // 4.销毁报文空间
            free(respdu);
            respdu = NULL;
            break;
        }
        // 根据用户名查找用户
        case ENUM_MSG_TYPE_SEARCH_USR_REQUEST: {
            // 1.根据用户名查找用户
            int ret = OpeDB::getInstance().handleSearchUsr(pdu->caData);
            // 2.组装返回数据
            PDU *respdu = mkPDU(0);
            respdu->uiMsgType = ENUM_MSG_TYPE_SEARCH_USR_RESPOND;
            if(-1 == ret) {
                strcpy(respdu->caData, SEARCH_USR_NO);
            }else if(1 == ret) {
                strcpy(respdu->caData, SEARCH_USR_ONLINE);
            }else if(0 == ret) {
                strcpy(respdu->caData, SEARCH_USR_OFFLINE);
            }
            // 3.返回响应
            write((char*)respdu,respdu->uiPDULen);
            // 4.销毁报文空间
            free(respdu);
            respdu = NULL;
            break;
        }
        // 添加好友
        case ENUM_MSG_TYPE_ADD_FRIEND_REQUEST: {
            char caPerName[32] = {'\0'};
            char caName[32] = {'\0'};
            strncpy(caPerName, pdu->caData,32);
            strncpy(caName,pdu->caData+32,32);
            int ret = OpeDB::getInstance().handleAddFriend(caPerName,caName);

            PDU *respdu = NULL;
            respdu = mkPDU(0);
            respdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_RESPOND;

            if(strcmp(caPerName, caName) == 0) {
                strcpy(respdu->caData, "不能添加自己为好友");
                write((char*)respdu,respdu->uiPDULen);
                free(respdu);
                respdu = NULL;
            }else if(-1 == ret) {
                strcpy(respdu->caData, UNKNOW_ERROR);
                write((char*)respdu,respdu->uiPDULen);
                free(respdu);
                respdu = NULL;
            } else if (0 == ret){
                strcpy(respdu->caData, EXISTED_FRIEND);
                write((char*)respdu,respdu->uiPDULen);
                free(respdu);
                respdu = NULL;
            } else if (2 == ret){
                strcpy(respdu->caData, ADD_FRIEND_OFFLINE);
                write((char*)respdu,respdu->uiPDULen);
                free(respdu);
                respdu = NULL;
            } else if (3 == ret){
                strcpy(respdu->caData, ADD_FRIEND_NO_EXIST);
                write((char*)respdu,respdu->uiPDULen);
                free(respdu);
                respdu = NULL;
            } else if (1 == ret){
                MyTcpServer::getInstance().resend(caPerName, pdu);
            }
            break;
        }
        // 被对方同意添加好友
        case ENUM_MSG_TYPE_ADD_FRIEND_AGREE: {
            MyTcpServer::getInstance().handleAddFriendResponse(pdu);
            break;
        }
        // 被对方拒绝添加好友
        case ENUM_MSG_TYPE_ADD_FRIEND_REFUSE: {
            MyTcpServer::getInstance().handleAddFriendResponse(pdu);
            break;
        }
        // 刷新好友列表请求
        case ENUM_MSG_TYPE_FLUSH_FRIEND_REQUEST: {
            char strName[32] = {'\0'};
            strncpy(strName, pdu->caData,32);
            QStringList ret = OpeDB::getInstance().handleFlushFriend(strName);
            uint uiMsgLen = ret.size()*32;
            PDU *respdu = mkPDU(uiMsgLen);
            respdu->uiMsgType = ENUM_MSG_TYPE_FLUSH_FRIEND_RESPOND;
            for(int i = 0; i < ret.size(); i++) {
                memcpy((char*)(respdu->caMsg) + i*32, ret.at(i).toStdString().c_str(), ret.at(i).size());
            }
            write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = NULL;
            break;
        }
        // 删除好友请求
        case ENUM_MSG_TYPE_DELETE_FRIEND_REQUEST: {
            char selfName[32] = {'\0'};
            char friendName[32] = {'\0'};
            strncpy(selfName, pdu->caData,32);
            strncpy(friendName,pdu->caData+32,32);
            bool ret = OpeDB::getInstance().handleDelFriend(selfName, friendName);
            if(ret) {
                pdu ->uiMsgType = ENUM_MSG_TYPE_DELETE_FRIEND_RESPOND;
                write((char*)pdu,pdu->uiPDULen);
            }
            break;
        }
        default:{
            break;
        }
    }
    free(pdu);
    pdu = NULL;
}

void MyTcpSocket::clientOffline()
{
    OpeDB::getInstance().handleOffline(m_strName.toStdString().c_str());
    // 发送信号
    emit offline(this);
}











